#include "../include/stdio.h"
#include "../include/console.h"
#include "../include/types.h"
#include "../include/stdarg.h"
#include <stddef.h>

// 数字转换用的字符表
static const char digits[] = "0123456789ABCDEF";

// 函数指针类型：字符输出函数
typedef void (*putc_func)(char c, void *ctx);

// sprintf 上下文结构体
struct sprintf_ctx {
    char *buf;
    int pos;
};

// 提前声明函数（参数列表与定义完全一致）
static void print_number(putc_func putc, void *ctx, uint64 num, int base, int sign, int is_signed);
static void sprintf_putc(char c, void *ctx);

// 数字转换核心函数
static void print_number(putc_func putc, void *ctx, uint64 num, int base, int sign, int is_signed) {
    char buf[32];
    int i = 0;
    int64 s_num;  // 用于处理有符号数

    // 处理有符号数（仅当 is_signed=1 且 num 为负数时）
    if (is_signed && (int64)num < 0) {
        s_num = (int64)num;
        num = (uint64)(-s_num);  // 转为无符号数处理，避免溢出
        putc('-', ctx);          // 输出负号
    }

    // 处理0的特殊情况
    if (num == 0) {
        buf[i++] = '0';
    } else {
        // 逆序转换数字为字符（如 123 → '3','2','1'）
        while (num > 0) {
            buf[i++] = digits[num % base];
            num /= base;
        }
    }

    // 正序输出数字
    while (i > 0) {
        putc(buf[--i], ctx);
    }
}

// 缓冲区输出回调函数（用于sprintf）
static void sprintf_putc(char c, void *ctx) {
    struct sprintf_ctx *sctx = (struct sprintf_ctx*)ctx;
    sctx->buf[sctx->pos++] = c;
}

// 通用格式化输出函数
static void vprintfmt(putc_func putc, void *ctx, const char *fmt, va_list ap) {
    for (; *fmt; fmt++) {
        if (*fmt != '%') {
            putc(*fmt, ctx);
            continue;
        }
        fmt++;  // 跳过'%'
        
        // 解析格式符
        switch (*fmt) {
            case 'd': {
                int num = va_arg(ap, int);
                print_number(putc, ctx, (uint64)num, 10, 1, 1);  // 有符号十进制
                break;
            }
            case 'x': {
                uint32 num = va_arg(ap, uint32);
                print_number(putc, ctx, (uint64)num, 16, 0, 0);  // 无符号十六进制
                break;
            }
            case 'p': {
                uint64 ptr = va_arg(ap, uint64);
                putc('0', ctx);
                putc('x', ctx);
                print_number(putc, ctx, ptr, 16, 0, 0);  // 指针（无符号十六进制）
                break;
            }
            case 's': {
                const char *s = va_arg(ap, const char*);
                if (!s) s = "(null)";
                for (; *s; s++) putc(*s, ctx);
                break;
            }
            case 'c': {
                int c = va_arg(ap, int);  // 可变参数会提升为int
                putc((char)c, ctx);       // 强转为char
                break;
            }
            case '%': {
                putc('%', ctx);
                break;
            }
            default: {
                putc('%', ctx);
                putc(*fmt, ctx);  // 未知格式符原样输出
                break;
            }
        }
    }
}

// 格式化输出到控制台
int printf(const char *fmt, ...) {
    va_list ap;
    va_start(ap, fmt);
    vprintfmt((putc_func)console_putc, NULL, fmt, ap);
    va_end(ap);
    return 0;
}

// 格式化输出到缓冲区
int sprintf(char *buf, const char *fmt, ...) {
    va_list ap;
    va_start(ap, fmt);
    
    struct sprintf_ctx ctx = {
        .buf = buf,
        .pos = 0
    };
    
    vprintfmt(sprintf_putc, &ctx, fmt, ap);
    buf[ctx.pos] = '\0';  // 添加字符串结束符
    
    va_end(ap);
    return ctx.pos;
}

// 带颜色的格式化输出
int printf_color(const char *color, const char *fmt, ...) {
    va_list ap;
    va_start(ap, fmt);
    
    console_puts(color);          // 设置颜色
    vprintfmt((putc_func)console_putc, NULL, fmt, ap);
    console_puts(COLOR_RESET);    // 重置颜色
    
    va_end(ap);
    return 0;
}
